package com.ggb.readingtime.config

import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.ggb.readingtime.constants.ACCESS_DENIED
import com.ggb.readingtime.constants.USER_ID
import com.ggb.readingtime.extension.log
import com.ggb.readingtime.properties.JwtProperties
import com.ggb.readingtime.service.JwtService
import lombok.AllArgsConstructor
import lombok.extern.slf4j.Slf4j
import org.springframework.http.HttpStatus
import org.springframework.stereotype.Component
import org.springframework.web.server.ServerWebExchange
import org.springframework.web.server.WebFilter
import org.springframework.web.server.WebFilterChain
import reactor.core.publisher.Mono
import com.ggb.readingtime.model.Result
import org.springframework.core.io.buffer.DataBuffer
import org.springframework.http.MediaType

@Component
@Slf4j
@AllArgsConstructor
class JwtTokenFilter(private val jwtService: JwtService,private  val jwtProperties: JwtProperties) : WebFilter {

    override fun filter(exchange: ServerWebExchange, chain: WebFilterChain): Mono<Void> {
        val request = exchange.request
        val path = request.path.value()
        // 放行Swagger相关的请求
        if (
            path.contains("/admin/login") ||
            path.contains("/user/login") ||
            path.startsWith("/v3/swagger-ui/") || // 为Swagger UI的路径
            path.startsWith("/v3/api-docs") || // 为API文档的路径
            path.startsWith("/v3/swagger-resources") || // 为Swagger的资源文件路径
            path.startsWith("/v3/webjars/") || // 为Swagger UI的webjars资源路径
            path == "/v3/swagger-ui.html"|| // 如果你的Swagger页面是这个路径
            path == "/v3/doc.html"
        ) return chain.filter(exchange)
        // 尝试获取客户端Token
        val token = jwtProperties.userTokenName?.let { exchange.request.headers.getFirst(it)?.substringAfter("Bearer ") }
        token?.let {
            val userId = jwtService.getUserIdFromToken(it)
            if (userId != null && jwtService.validateToken(it)) {
                // 通过客户端Token验证，将用户名设置为属性
                exchange.attributes[USER_ID] = userId
                return chain.filter(exchange)
            } else {
                return unauthorized(exchange)
            }
        }

        // 尝试获取后台Authorization Token
        val authorizationToken = jwtProperties.adminTokenName?.let { exchange.request.headers.getFirst(it)?.substringAfter("Bearer ") }
        authorizationToken?.let {
            val userId = jwtService.getUserIdFromAuthorizationToken(it)
            if (userId != null && jwtService.validateAuthorizationToken(it)) {
                // 通过后台Authorization Token验证，将用户名设置为属性
                exchange.attributes[USER_ID] = userId
                return chain.filter(exchange)
            } else {
                return unauthorized(exchange)
            }
        }

        // 如果两种Token都不存在或验证失败
        return unauthorized(exchange)
    }

    private fun unauthorized(exchange: ServerWebExchange): Mono<Void> {
        val result = unauthorizedResult() // 获取无权访问的Result对象
        val json = jacksonObjectMapper().writeValueAsString(result) // 将Result对象序列化为JSON字符串

        val response = exchange.response
        response.statusCode = HttpStatus.UNAUTHORIZED
        response.headers.contentType = MediaType.APPLICATION_JSON
        val buffer: DataBuffer = response.bufferFactory().wrap(json.toByteArray())
        return response.writeWith(Mono.just(buffer))
    }

    private fun unauthorizedResult(): Result<Any> {
        return Result(code = 401, msg = ACCESS_DENIED, data = null)
    }

}
